package com.dmx.cep.action.epgManage;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.struts2.config.DefaultSettings;
import org.dom4j.DocumentException;

import com.dmx.cep.entity.TvContentInfo;
import com.dmx.cep.entity.TvContentStatus;
import com.dmx.cep.service.EpgService;
import com.dmx.cep.util.EncodingDetecter;
import com.dmx.cep.util.EpgTextParse;
import com.dmx.fw.util.DateTimeUtils;
import com.dmx.fw.web.struts2.action.BaseAction;

public class EpgImportAction extends BaseAction{
	
	private EpgService epgService;
	
	private File epgFile;
	
	private String result;
	
	private String fileDir;
	
	public String execute() throws Exception{
		
		if("testFileExists".equals(this.act)){
			return testFileExists();
		}		
		
		if("doImport".equals(this.act)){
			return doImport();
		}
		
		return super.execute();
	}

	public EpgService getEpgService() {
		return epgService;
	}

	public void setEpgService(EpgService epgService) {
		this.epgService = epgService;
	}
	
	public String testFileExists() throws Exception{
		
		log.info("fileDir: "+fileDir);
		try {
			File f = new File(fileDir);

			if (f.exists()) {
				result="{msg:'true'}";
			}else{
				result="{msg:'false'}";
			}
		} catch (Exception e) {
			log.error(e);
			result="{msg:'false'}";
		}
		
		log.info("result:"+result);
		
		this.setAjaxResult(result);
		
		return null;
	}
	
	public String doImport() throws Exception{
		try {
			EpgTextParse textParse = null;
			
			EncodingDetecter ed=new EncodingDetecter();
			String encodeType=ed.preParse(epgFile.getPath(), null);
			
			log.info("EPG file encoding is : "+encodeType);
			
			if(encodeType!=null){
					
				textParse=new EpgTextParse(convertFile(encodeType,epgFile),epgService);
				
			}
			String language=DefaultSettings.get("struts.locale");
			textParse.parse(language);
			
			if(textParse.isErrorFlag()){
				String errorTime="";
				if(textParse.getErrorTime()!=null){
					errorTime=textParse.getErrorTime();
				}
				
				if("program.duration.less.than.mintime".equals(textParse.getErrorCode())){
					this.setErrorInfo(this.getText(textParse.getErrorCode())+textParse.PROGRAMME_MIN_DURATION+this.getText("minutes")+this.getText("error.time")+errorTime);
				}else if("program.duration.beyond.maxtime".equals(textParse.getErrorCode())){
					this.setErrorInfo(this.getText(textParse.getErrorCode())+textParse.PROGRAMME_MAX_DURATION+this.getText("minutes")+this.getText("error.time")+errorTime);
				}else{
					this.setErrorInfo(this.getText(textParse.getErrorCode())+errorTime);
				}
				return SUCCESS;
			}
			
			String channelCode=textParse.getChannelCode();
			if(channelCode==null){
				//error when the channel's name couldn't be found in xml
				this.setErrorInfo(this.getText("channel.not.exists"));
				return SUCCESS;
			}else{
				if(!epgService.isChannelExists(channelCode)){
					this.setErrorInfo(this.getText("channel.not.exists"));
					return SUCCESS;
				}
			}
			
			Date epgStartTime=textParse.getProgramStartTime();
			log.info("epg start time="+DateTimeUtils.DateToString(epgStartTime, "yyyy-MM-dd HH:mm:ss"));
			if(epgStartTime==null){
				this.setErrorInfo(this.getText("no.programs.to.import"));
				return SUCCESS;
			}
			
			List<TvContentInfo> tvContentList = textParse.getTvContentList();
			
			List<TvContentStatus> tvContentStatusList=textParse.getTvContentStatusList();
			
			epgService.batchOverWritePrograms(channelCode, epgStartTime, tvContentList, tvContentStatusList);
			
			this.setSuccessinfo(this.getText("epg.import.success")+tvContentList.size());
		}catch(DocumentException de){
			de.printStackTrace();
			log.error(de);
			this.setErrorInfo(this.getText("epg.parse.error"));
		}
		catch (Exception e) {
			log.error(e);
			e.printStackTrace();
			this.setErrorInfo(this.getText("epg.import.failed"));
		}

		return SUCCESS;
	}
	
	private InputStream convertFile(String encodeType, File file)
			throws FileNotFoundException, IOException {

		if ("windows-1252".equals(encodeType)) {
			encodeType = "Unicode";
		}
		
		
		List<String> lines=IOUtils.readLines(new FileInputStream(file),encodeType);
		if("UTF-8".equalsIgnoreCase(encodeType)){
			if(lines!=null&&lines.size()>0){
				String firstLine=lines.get(0);
				firstLine=removeBomCharacter(firstLine);
				lines.set(0,firstLine.trim());
			}
		}
		
		StringBuffer sb=new StringBuffer();
		for(String line:lines){
			sb.append(line);
		}
		
		ByteArrayInputStream in=new ByteArrayInputStream(sb.toString().getBytes(encodeType));
		
		//FileInputStream fis = new FileInputStream(file);
		//InputStreamReader isr = new InputStreamReader(fis, encodeType);

		//Reader in = new BufferedReader(isr);
		return in;
	}
	
	private String removeBomCharacter(String str){
		try {
			byte[] bytes = str.getBytes("UTF-8");
			for(int i=0;i<bytes.length;i++){
				if(i>0) break;
				int temp=bytes[i];
				String hexString=Integer.toHexString(temp);
				if(hexString.length()<2) break;
				// 1个byte变成16进制的，只需要2位就可以表示了，取后面两位，去掉前面的符号填充
				hexString=hexString.substring(hexString.length()-2);
				log.info(hexString.toUpperCase());
				if(hexString.toUpperCase().equals("EF")){
					str=new String(bytes,3,bytes.length-3,"UTF-8");  //去掉BOM字符
					break;
				}
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			log.error(e);
		}
		return str;
	}

	public File getEpgFile() {
		return epgFile;
	}

	public void setEpgFile(File epgFile) {
		this.epgFile = epgFile;
	}

	public String getFileDir() {
		return fileDir;
	}

	public void setFileDir(String fileDir) {
		this.fileDir = fileDir;
	}

	public String getResult() {
		return result;
	}

	public void setResult(String result) {
		this.result = result;
	}
	
}
